﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Yz.Base.Config;
using Yz.Model.Views;

namespace Yz.Web
{
    public class JwtManager
    {
        /// <summary>
        /// 创建token 
        /// </summary>
        /// <param name="identity"></param>
        /// <param name="expireMinutes"></param>
        /// <returns></returns>
        public static string GenerateToken(VmUserBase user, List<string> roleNameList, JwtConfig jwtConfig)
        {
            var dtNow = DateTime.Now;
            var expTime = dtNow.AddMinutes(jwtConfig.Expires);
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecretKey));

            //Claims (Payload)  Claims 部分包含了一些跟这个token有关的重要信息 JWT 标准规定了一些字段
            var claims = new List<Claim>{//下边为Claim的默认配置
                //jti: JWT ID，针对当前 token 的唯一标识
                new Claim(JwtRegisteredClaimNames.Jti, user.Id.ToString()),
                //iat: Issued At,token 创建时间,Unix 时间戳格式
                new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(dtNow).ToUnixTimeSeconds()}"),
                //nbf: Not Before,token实现回旋余地,通常不超过几分钟,以解释时钟倾斜,Unix 时间戳格式
                new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(dtNow.AddSeconds(30)).ToUnixTimeSeconds()}") ,
                //exp: Expiration Time,token过期时间，Unix 时间戳格式
                new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(expTime).ToUnixTimeSeconds()}"),
                //iss: The issuer of the token,token发送方
                new Claim(JwtRegisteredClaimNames.Iss,jwtConfig.Issuer),
                //aud: audience,token接收方
                new Claim(JwtRegisteredClaimNames.Aud,jwtConfig.Audience),
                //这个Role是官方UseAuthentication要要验证的Role，我们就不用手动设置Role这个属性了
                new Claim(ClaimTypes.NameIdentifier,user.Id.ToString()),
                //new Claim(ClaimTypes.Role,roleName),
                new Claim(ClaimTypes.Name, user.Name),
                //自定义扩展配置 
                new Claim(ClaimTypes.GivenName, user.LoginName),
                new Claim(ClaimTypes.Email, user.CompanyId.ToString()),
            };
            foreach (var role in roleNameList)
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }

            var creds = new JwtSecurityToken(
                issuer: jwtConfig.Issuer,
                audience: jwtConfig.Audience,
                claims: claims,
                notBefore: dtNow.AddSeconds(30),
                expires: expTime,
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
                );
            var tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.WriteToken(creds);
            return token;
        }
    }
}
